package com.gitee.dolt.core.converter;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonStreamContext;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;


/**
 * enum反序列化工具。。。 此类有bug，当同出现 {a:{},b:xx},b为枚举，前面出现a为空对象时会出现b无法解析的情况。
 * <p>
 * 字段类型是枚举类型时，可以按照以下2种格式反序列化：
 * 1. 字符串形式：字段名： "XX"
 * 2. 对象形式： 字段名： {
 * "code": "XX"
 * }
 *
 * @author LYH
 */
@Slf4j
public class EnumDeserializer extends StdDeserializer<Enum<?>> {
    public static final EnumDeserializer INSTANCE = new EnumDeserializer();


    public EnumDeserializer() {
        super(Enum.class);
    }

    @Override
    public Enum<?> deserialize(JsonParser jp, DeserializationContext context) {
        try {
            // 读取
            JsonNode node = jp.getCodec().readTree(jp);
            // 当前字段
            String currentName = jp.currentName();
            // 当前对象
            Object currentValue = jp.getCurrentValue();
            Class propertyType;
            if (currentValue instanceof Collection) {
                JsonStreamContext parsingContext = jp.getParsingContext();
                JsonStreamContext parent = parsingContext.getParent();
                Object currentValue3 = parent.getCurrentValue();
                String currentName3 = parent.getCurrentName();
                Field listField = currentValue3.getClass().getDeclaredField(currentName3);
                ParameterizedType listGenericType = (ParameterizedType) listField.getGenericType();
                Type listActualTypeArguments = listGenericType.getActualTypeArguments()[0];
                propertyType = (Class) listActualTypeArguments;
            } else {
                // 在对象中找到改字段
                propertyType = BeanUtils.findPropertyType(currentName, currentValue.getClass());
            }
            JsonNode code = node.get(EnumSerializer.ALL_ENUM_KEY_FIELD);
            String val = code != null ? code.asText() : node.asText();
            if (StrUtil.isBlank(val) || StrUtil.NULL.equals(val)) {
                return null;
            }
            return Enum.valueOf(propertyType, val);
        } catch (Exception e) {
            log.warn("解析枚举失败", e);
            return null;
        }
    }


}
